new darwin patches

Поиск
Список
Период
Сортировка
От Peter Bierman
Тема new darwin patches
Дата
Msg-id v03130303b655c9dc9b6c@[17.202.21.230]
обсуждение исходный текст
Ответы Re: new darwin patches  (Tom Lane <tgl@sss.pgh.pa.us>)
Re: new darwin patches  (Tom Lane <tgl@sss.pgh.pa.us>)
Список pgsql-patches
Here are my latest patches to PG top of tree that allow PG to build, install,
and pass the regression tests on darwin (Mac OS X).

Thanks for all the suggestions. I think I've taken care of all of the issues
mentioned to me so far.

-pmb

New directory: src/backend/port/darwin/
===================================================================

New file: src/backend/port/darwin/Makefile
===================================================================
#-------------------------------------------------------------------------
#
# Makefile--
#    Makefile for port/darwin
#
# IDENTIFICATION
#    $Header: $
#
#-------------------------------------------------------------------------

subdir = src/backend/port/darwin
top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global

OBJS = sem.o

all: SUBSYS.o

SUBSYS.o: $(OBJS)
        $(LD) $(LDREL) $(LDOUT) SUBSYS.o $(OBJS)

depend dep:
        $(CC) -MM $(CFLAGS) *.c >depend

clean:
        rm -f SUBSYS.o $(OBJS)

ifeq (depend,$(wildcard depend))
include depend
endif

New file: src/backend/port/darwin/sem.h
cp src/backend/port/qnx4/sem.h src/backend/port/darwin/sem.h
% diff -u src/backend/port/qnx4/sem.h src/backend/port/darwin/sem.h
===================================================================
--- src/backend/port/qnx4/sem.h Wed Apr 12 10:15:30 2000
+++ src/backend/port/darwin/sem.h       Fri Dec  1 01:07:05 2000
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /home/projects/pgsql/cvsroot/pgsql/src/backend/port/qnx4/sem.h,v 1.3 2000/04/12 17:15:30 momjian Exp
$
+ *       $Header: $
  *
  *-------------------------------------------------------------------------
  */
@@ -15,6 +15,8 @@
 #ifndef _SYS_SEM_H
 #define _SYS_SEM_H

+/* #define DEBUG_IPC here if you want to see the shim in action */
+
 #include <sys/ipc.h>

 #ifdef __cplusplus
@@ -33,6 +35,10 @@
 #define GETZCNT 7                              /* get semzcnt */
 #define SETVAL 8                               /* set semval */
 #define SETALL 9                               /* set all semval's */
+
+#ifndef ushort_t
+#define ushort_t unsigned int
+#endif

 /*
  *     There is one semaphore structure for each semaphore in the system.

New file: src/backend/port/darwin/sem.c
cp src/backend/port/qnx4/sem.c src/backend/port/darwin/sem.c
% diff -u src/backend/port/qnx4/sem.c src/backend/port/darwin/sem.c
===================================================================
--- src/backend/port/qnx4/sem.c Wed Apr 12 10:15:30 2000
+++ src/backend/port/darwin/sem.c       Fri Dec  1 01:05:19 2000
@@ -4,10 +4,13 @@
  *       System V Semaphore Emulation
  *
  * Copyright (c) 1999, repas AEG Automation GmbH
- *
+ *
+ * 2000-12-1 pmb@mac.com
+ *   - changed from anonymous to named semaphores for darwin
+ *   - this required changing sem_info from containig an array of sem_t to an array of sem_t*
  *
  * IDENTIFICATION
- *       $Header: /home/projects/pgsql/cvsroot/pgsql/src/backend/port/qnx4/sem.c,v 1.3 2000/04/12 17:15:30 momjian Exp
$
+ *       $Header: $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,16 +25,15 @@
 #include "postgres.h"
 #include "storage/ipc.h"
 #include "storage/proc.h"
-#include <sys/sem.h>
-
+#include "sem.h"

-#define SETMAX ((MAXBACKENDS + PROC_NSEMS_PER_SET - 1) / PROC_NSEMS_PER_SET)
-#define SEMMAX (PROC_NSEMS_PER_SET)
+#define SEMMAX  IPC_NMAXSEM
+#define SETMAX ((MAXBACKENDS + SEMMAX - 1) / SEMMAX)
 #define OPMAX  8

 #define MODE   0700
 #define SHM_INFO_NAME  "SysV_Sem_Info"
-
+#define SEM_NAME       "/pgsql-darwin"

 struct pending_ops
 {
@@ -41,12 +43,12 @@

 struct sem_info
 {
-       sem_t           sem;
+       sem_t*          sem;
        struct
        {
                key_t           key;
                int                     nsems;
-               sem_t           sem[SEMMAX];/* array of POSIX semaphores */
+               sem_t*          sem[SEMMAX];/* array of POSIX semaphores */
                struct sem      semV[SEMMAX];           /* array of System V semaphore
                                                                                 * structures */
                struct pending_ops pendingOps[SEMMAX];  /* array of pending
@@ -62,12 +64,12 @@
 {
        int                     r = 0;

-       sem_wait(&SemInfo->sem);
+       sem_wait(SemInfo->sem);

        if (semid < 0 || semid >= SETMAX ||
                semnum < 0 || semnum >= SemInfo->set[semid].nsems)
        {
-               sem_post(&SemInfo->sem);
+               sem_post(SemInfo->sem);
                errno = EINVAL;
                return -1;
        }
@@ -107,7 +109,7 @@
                case IPC_RMID:
                        for (semnum = 0; semnum < SemInfo->set[semid].nsems; semnum++)
                        {
-                               if (sem_destroy(&SemInfo->set[semid].sem[semnum]) == -1)
+                               if (sem_close(SemInfo->set[semid].sem[semnum]) == -1)
                                        r = -1;
                        }
                        SemInfo->set[semid].key = -1;
@@ -115,12 +117,12 @@
                        break;

                default:
-                       sem_post(&SemInfo->sem);
+                       sem_post(SemInfo->sem);
                        errno = EINVAL;
                        return -1;
        }

-       sem_post(&SemInfo->sem);
+       sem_post(SemInfo->sem);

        return r;
 }
@@ -132,9 +134,13 @@
                                semid,
                                semnum /* , semnum1 */ ;
        int                     exist = 0;
+       char                    semname[64];

        if (nsems < 0 || nsems > SEMMAX)
        {
+#ifdef DEBUG_IPC
+               fprintf(stderr, "darwin semget aborting because nsems out of range. (%d)\n", nsems);
+#endif
                errno = EINVAL;
                return -1;
        }
@@ -142,6 +148,9 @@
        /* open and map shared memory */
        if (SemInfo == (struct sem_info *) - 1)
        {
+#ifdef DEBUG_IPC
+               fprintf(stderr, "darwin initializing shared mem for semaphore shim.\n");
+#endif
                /* test if the shared memory already exists */
                fd = shm_open(SHM_INFO_NAME, O_RDWR | O_CREAT | O_EXCL, MODE);
                if (fd == -1 && errno == EEXIST)
@@ -152,7 +161,7 @@
                if (fd == -1)
                        return fd;
                /* The size may only be set once. Ignore errors. */
-               ltrunc(fd, sizeof(struct sem_info), SEEK_SET);
+               ftruncate(fd, sizeof(struct sem_info));
                SemInfo = mmap(NULL, sizeof(struct sem_info),
                                           PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
                if (SemInfo == MAP_FAILED)
@@ -160,17 +169,21 @@
                if (!exist)
                {
                        /* create semaphore for locking */
-                       sem_init(&SemInfo->sem, 1, 1);
-                       sem_wait(&SemInfo->sem);
+                       sprintf(semname, "%s-map", SEM_NAME);
+#ifdef DEBUG_IPC
+                       fprintf(stderr, "darwin creating sem %s to cover shared mem.\n", semname);
+#endif
+                       SemInfo->sem = sem_open(semname, O_CREAT, semflg & 0777, 1);
+                       sem_wait(SemInfo->sem);
                        /* initilize shared memory */
                        memset(SemInfo->set, 0, sizeof(SemInfo->set));
                        for (semid = 0; semid < SETMAX; semid++)
                                SemInfo->set[semid].key = -1;
-                       sem_post(&SemInfo->sem);
+                       sem_post(SemInfo->sem);
                }
        }

-       sem_wait(&SemInfo->sem);
+       sem_wait(SemInfo->sem);

        if (key != IPC_PRIVATE)
        {
@@ -180,7 +193,7 @@
                        semid++;
                if (!(semflg & IPC_CREAT) && semid >= SETMAX)
                {
-                       sem_post(&SemInfo->sem);
+                       sem_post(SemInfo->sem);
                        errno = ENOENT;
                        return -1;
                }
@@ -188,7 +201,7 @@
                {
                        if (semflg & IPC_CREAT && semflg & IPC_EXCL)
                        {
-                               sem_post(&SemInfo->sem);
+                               sem_post(SemInfo->sem);
                                errno = EEXIST;
                                return -1;
                        }
@@ -196,11 +209,15 @@
                        {
                                if (nsems != 0 && SemInfo->set[semid].nsems < nsems)
                                {
-                                       sem_post(&SemInfo->sem);
+#ifdef DEBUG_IPC
+fprintf(stderr, "darwin semget failed because if (nsems != 0 && SemInfo->set[semid].nsems < nsems) %d %d\n",
+       nsems, SemInfo->set[semid].nsems);
+#endif
+                                       sem_post(SemInfo->sem);
                                        errno = EINVAL;
                                        return -1;
                                }
-                               sem_post(&SemInfo->sem);
+                               sem_post(SemInfo->sem);
                                return semid;
                        }
                }
@@ -212,20 +229,28 @@
                semid++;
        if (semid >= SETMAX)
        {
-               sem_post(&SemInfo->sem);
+#ifdef DEBUG_IPC
+               fprintf(stderr, "darwin semget failed because all keys were -1 up to SETMAX\n");
+#endif
+               sem_post(SemInfo->sem);
                errno = ENOSPC;
                return -1;
        }

        for (semnum = 0; semnum < nsems; semnum++)
        {
-               sem_init(&SemInfo->set[semid].sem[semnum], 1, 0);
+               sprintf(semname, "%s-%d-%d", SEM_NAME, semid, semnum);
+#ifdef DEBUG_IPC
+               fprintf(stderr, "darwin creating sem %s to cover set %d num %dm.\n", semname, semid, semnum);
+#endif
+               SemInfo->set[semid].sem[semnum] = sem_open(semname, O_CREAT, semflg & 0777, 0);
+
 /* Currently sem_init always returns -1.
        if( sem_init( &SemInfo->set[semid].sem[semnum], 1, 0 ) == -1 )  {
          for( semnum1 = 0; semnum1 < semnum; semnum1++ )  {
-               sem_destroy( &SemInfo->set[semid].sem[semnum1] );
+               sem_close( SemInfo->set[semid].sem[semnum1] );
          }
-         sem_post( &SemInfo->sem );
+         sem_post( SemInfo->sem );
          return -1;
        }
 */
@@ -234,7 +259,7 @@
        SemInfo->set[semid].key = key;
        SemInfo->set[semid].nsems = nsems;

-       sem_post(&SemInfo->sem);
+       sem_post(SemInfo->sem);

        return semid;
 }
@@ -248,11 +273,11 @@
                                errno1 = 0,
                                op;

-       sem_wait(&SemInfo->sem);
+       sem_wait(SemInfo->sem);

        if (semid < 0 || semid >= SETMAX)
        {
-               sem_post(&SemInfo->sem);
+               sem_post(SemInfo->sem);
                errno = EINVAL;
                return -1;
        }
@@ -260,7 +285,7 @@
        {
                if ( /* sops[i].sem_num < 0 || */ sops[i].sem_num >= SemInfo->set[semid].nsems)
                {
-                       sem_post(&SemInfo->sem);
+                       sem_post(SemInfo->sem);
                        errno = EFBIG;
                        return -1;
                }
@@ -274,7 +299,7 @@
                        {
                                if (sops[i].sem_flg & IPC_NOWAIT)
                                {
-                                       sem_post(&SemInfo->sem);
+                                       sem_post(SemInfo->sem);
                                        errno = EAGAIN;
                                        return -1;
                                }
@@ -282,15 +307,15 @@
                                if (SemInfo->set[semid].pendingOps[sops[i].sem_num].idx >= OPMAX)
                                {
                                        /* pending operations array overflow */
-                                       sem_post(&SemInfo->sem);
+                                       sem_post(SemInfo->sem);
                                        errno = ERANGE;
                                        return -1;
                                }

SemInfo->set[semid].pendingOps[sops[i].sem_num].op[SemInfo->set[semid].pendingOps[sops[i].sem_num].idx++]=
sops[i].sem_op;
                                /* suspend */
-                               sem_post(&SemInfo->sem);                /* avoid deadlock */
-                               r1 = sem_wait(&SemInfo->set[semid].sem[sops[i].sem_num]);
-                               sem_wait(&SemInfo->sem);
+                               sem_post(SemInfo->sem);         /* avoid deadlock */
+                               r1 = sem_wait(SemInfo->set[semid].sem[sops[i].sem_num]);
+                               sem_wait(SemInfo->sem);
                                if (r1)
                                {
                                        errno1 = errno;
@@ -314,7 +339,7 @@
                                if
(SemInfo->set[semid].pendingOps[sops[i].sem_num].op[SemInfo->set[semid].pendingOps[sops[i].sem_num].idx- 1] + op >= 0) 
                                {
                                        /* unsuspend processes */
-                                       if (sem_post(&SemInfo->set[semid].sem[sops[i].sem_num]))
+                                       if (sem_post(SemInfo->set[semid].sem[sops[i].sem_num]))
                                        {
                                                errno1 = errno;
                                                r = -1;
@@ -335,14 +360,14 @@
                        /* sops[i].sem_op == 0 */
                {
                        /* not supported */
-                       sem_post(&SemInfo->sem);
+                       sem_post(SemInfo->sem);
                        errno = ENOSYS;
                        return -1;
                }
                SemInfo->set[semid].semV[sops[i].sem_num].sempid = getpid();
        }

-       sem_post(&SemInfo->sem);
+       sem_post(SemInfo->sem);

        errno = errno1;
        return r;

Index: src/backend/port/Makefile.in
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/port/Makefile.in,v
retrieving revision 1.27
diff -u -r1.27 Makefile.in
--- src/backend/port/Makefile.in    2000/10/20 21:03:45    1.27
+++ src/backend/port/Makefile.in    2000/12/07 22:50:54
@@ -30,6 +30,10 @@
 ifeq ($(PORTNAME), beos)
 OBJS += beos/SUBSYS.o
 endif
+ifeq ($(PORTNAME), darwin)
+OBJS += darwin/SUBSYS.o
+endif
+
 all: SUBSYS.o

 SUBSYS.o: $(OBJS)
@@ -45,11 +49,19 @@
 beos.dir:
     $(MAKE) -C beos all

+darwin/SUBSYS.o: darwin.dir
+
+darwin.dir:
+    $(MAKE) -C darwin all
+
 tas.o: tas.s
     $(CC) $(CFLAGS) -c $<

 distclean clean:
     rm -f SUBSYS.o $(OBJS)
+    $(MAKE) -C beos clean
+    $(MAKE) -C darwin clean
+    $(MAKE) -C qnx4 clean

 depend dep:
     $(CC) -MM $(CFLAGS) *.c >depend
Index: src/backend/port/dynloader/darwin.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/port/dynloader/darwin.c,v
retrieving revision 1.3
diff -u -r1.3 darwin.c
--- src/backend/port/dynloader/darwin.c    2000/11/14 21:26:21    1.3
+++ src/backend/port/dynloader/darwin.c    2000/12/07 22:50:54
@@ -10,7 +10,7 @@
 #include <mach-o/dyld.h>
 #include "dynloader.h"

-void *pg_dlopen(const char *filename)
+void *pg_dlopen(char *filename)
 {
     NSObjectFileImage image;

@@ -26,18 +26,26 @@
     return;
 }

-PGFunction pg_dlsym(void *handle, const char *funcname)
+PGFunction pg_dlsym(void *handle, char *funcname)
 {
     NSSymbol symbol;
     char *symname = (char*)malloc(strlen(funcname)+2);

     sprintf(symname, "_%s", funcname);
-    symbol = NSLookupAndBindSymbol(symname);
-    free(symname);
-    return (PGFunction) NSAddressOfSymbol(symbol);
+    if (NSIsSymbolNameDefined(symname))
+    {
+        symbol = NSLookupAndBindSymbol(symname);
+        free(symname);
+        return (PGFunction) NSAddressOfSymbol(symbol);
+    }
+    else
+    {
+        free(symname);
+        return (PGFunction)NULL;
+    }
 }

-const char *pg_dlerror(void)
+char *pg_dlerror(void)
 {
     return "no error message available";
 }
Index: src/backend/port/dynloader/darwin.h
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/port/dynloader/darwin.h,v
retrieving revision 1.2
diff -u -r1.2 darwin.h
--- src/backend/port/dynloader/darwin.h    2000/11/09 19:00:50    1.2
+++ src/backend/port/dynloader/darwin.h    2000/12/07 22:50:54
@@ -2,7 +2,7 @@

 #include "fmgr.h"

-void       *pg_dlopen(const char *filename);
-PGFunction    pg_dlsym(void *handle, const char *funcname);
+void*        pg_dlopen(char *filename);
+PGFunction    pg_dlsym(void *handle, char *funcname);
 void        pg_dlclose(void *handle);
-const char *pg_dlerror(void);
+char*        pg_dlerror(void);
Index: src/backend/storage/buffer/s_lock.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/storage/buffer/s_lock.c,v
retrieving revision 1.26
diff -u -r1.26 s_lock.c
--- src/backend/storage/buffer/s_lock.c    2000/11/28 23:27:55    1.26
+++ src/backend/storage/buffer/s_lock.c    2000/12/07 22:50:54
@@ -119,6 +119,35 @@

 #endif     /* __m68k__ */

+#if defined(__APPLE__) && defined(__ppc__)
+/* used in darwin. */
+/* We key off __APPLE__ here because this function differs from
+ * the LinuxPPC implementation only in compiler syntax.
+ */
+static void
+tas_dummy()
+{
+       __asm__("               \n\
+               .globl  tas     \n\
+               .globl  _tas    \n\
+_tas:                          \n\
+tas:                           \n\
+               lwarx   r5,0,r3 \n\
+               cmpwi   r5,0    \n\
+               bne     fail    \n\
+               addi    r5,r5,1 \n\
+               stwcx.  r5,0,r3 \n\
+               beq     success \n\
+fail:          li      r3,1    \n\
+               blr             \n\
+success:                       \n\
+               li r3,0         \n\
+               blr             \n\
+    ");
+}
+
+#endif  /* __APPLE__ && __ppc__ */
+
 #if defined(__powerpc__)
 /* Note: need a nice gcc constrained asm version so it can be inlined */
 static void
Index: src/backend/storage/ipc/Makefile
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/storage/ipc/Makefile,v
retrieving revision 1.15
diff -u -r1.15 Makefile
--- src/backend/storage/ipc/Makefile    2000/10/20 21:03:47    1.15
+++ src/backend/storage/ipc/Makefile    2000/12/07 22:50:54
@@ -15,6 +15,10 @@
 endif
 endif

+ifeq ($(PORTNAME), darwin)
+CFLAGS += -D__darwin__ -I../../port/darwin/
+endif
+
 OBJS = ipc.o ipci.o shmem.o shmqueue.o sinval.o \
        sinvaladt.o spin.o

Index: src/backend/storage/ipc/ipc.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/storage/ipc/ipc.c,v
retrieving revision 1.54
diff -u -r1.54 ipc.c
--- src/backend/storage/ipc/ipc.c    2000/11/28 23:27:56    1.54
+++ src/backend/storage/ipc/ipc.c    2000/12/07 22:50:54
@@ -52,6 +52,10 @@
 #include <sys/ipc.h>
 #endif

+#if defined(__darwin__)
+#include "sem.h"
+#endif
+

 /*
  * This flag is set during proc_exit() to change elog()'s behavior,
Index: src/backend/storage/ipc/spin.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/storage/ipc/spin.c,v
retrieving revision 1.26
diff -u -r1.26 spin.c
--- src/backend/storage/ipc/spin.c    2000/11/28 23:27:56    1.26
+++ src/backend/storage/ipc/spin.c    2000/12/07 22:50:55
@@ -21,7 +21,7 @@
 #include "postgres.h"

 #include <errno.h>
-#ifndef HAS_TEST_AND_SET
+#if !defined(HAS_TEST_AND_SET) && defined(HAVE_SYS_SEM_H)
 #include <sys/sem.h>
 #endif

Index: src/backend/storage/lmgr/Makefile
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/storage/lmgr/Makefile,v
retrieving revision 1.14
diff -u -r1.14 Makefile
--- src/backend/storage/lmgr/Makefile    2000/08/31 16:10:36    1.14
+++ src/backend/storage/lmgr/Makefile    2000/12/07 22:50:55
@@ -12,6 +12,10 @@
 top_builddir = ../../../..
 include $(top_builddir)/src/Makefile.global

+ifeq ($(PORTNAME), darwin)
+CFLAGS += -D__darwin__ -I../../port/darwin/
+endif
+
 OBJS = lmgr.o lock.o proc.o

 all: SUBSYS.o
Index: src/backend/storage/lmgr/proc.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v
retrieving revision 1.84
diff -u -r1.84 proc.c
--- src/backend/storage/lmgr/proc.c    2000/11/28 23:27:56    1.84
+++ src/backend/storage/lmgr/proc.c    2000/12/07 22:50:55
@@ -69,6 +69,11 @@
 #include <sys/sem.h>
 #endif

+/* Darwin needs a shim for semctl */
+#if defined(__darwin__)
+#include "sem.h"
+#endif
+
 #include "storage/proc.h"

 void        HandleDeadLock(SIGNAL_ARGS);
Index: src/include/port/darwin.h
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/include/port/darwin.h,v
retrieving revision 1.1
diff -u -r1.1 darwin.h
--- src/include/port/darwin.h    2000/10/31 19:55:19    1.1
+++ src/include/port/darwin.h    2000/12/07 22:50:55
@@ -1,5 +1,8 @@
+#if defined(__ppc__)
 #define HAS_TEST_AND_SET
-#if defined(__powerpc__)
+#endif
+
+#if defined(__ppc__)
 typedef unsigned int slock_t;
 #else
 typedef unsigned char slock_t;
Index: src/makefiles/Makefile.darwin
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/makefiles/Makefile.darwin,v
retrieving revision 1.2
diff -u -r1.2 Makefile.darwin
--- src/makefiles/Makefile.darwin    2000/11/14 21:23:47    1.2
+++ src/makefiles/Makefile.darwin    2000/12/07 22:50:56
@@ -1,4 +1,5 @@
 AROPT = cr
+AWK= awk

 DLSUFFIX = .so
 CFLAGS_SL = -bundle -undefined suppress
Index: src/template/darwin
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/template/darwin,v
retrieving revision 1.1
diff -u -r1.1 darwin
--- src/template/darwin    2000/10/31 19:55:20    1.1
+++ src/template/darwin    2000/12/07 22:50:56
@@ -1,4 +1,3 @@
-# regular cpp is broken in current development releases
+# -traditional-cpp means "don't use apple's cpp-precomp" on darwin
+# this should change to -no-cpp-precomp when that flag is implemented
 CC="$CC -traditional-cpp"
-# be on safe side while they sort out their compiler
-CFLAGS=-O0

--
"Every time you provide an option, you're asking the user to make a decision.
 That means they will have to think about something and decide about it.
 It's not necessarily a bad thing, but, in general, you should always try to
 minimize the number of decisions that people have to make."
 http://joel.editthispage.com/stories/storyReader$51



В списке pgsql-patches по дате отправления:

Предыдущее
От: Michael Fork
Дата:
Сообщение: ODBC Driver patch
Следующее
От: Tom Lane
Дата:
Сообщение: Re: new darwin patches